/*
 * Copyright (c) 2009. Silenus Consultoria, S.L.
 */

/**
 * This file contains common control and definitions shared among modules,
 * it must be included before any other DETECTA's javascript file (but after ExtJS).
 */

Ext.namespace("Common");

Common.NIF_LETTERS = "TRWAGMYFPDXBNJZSQVHLCKE";

Common.checksumNIF = function(NIF) {
	if(NIF.length == 8) {
		var posIni = (NIF % Common.NIF_LETTERS.length);
		return Common.NIF_LETTERS.substring(posIni, posIni+1);
	}
	return '';
};

Common.validateNIF = function(NIF) {
	if(/^([0-9]|X|Y|Z)[0-9]{7}[A-Z]$/.test(NIF)) {
		var firstChar = NIF.charAt(0);
	  var crcChar = NIF.charAt(8);
		if(isNaN(firstChar)) {
			switch(firstChar) {
				case 'X':
					firstChar = '0';
					break;
				case 'Y':
					firstChar = '1';
					break;
				case 'Z':
					firstChar = '2';
					break;
			}
			return Common.checksumNIF(firstChar.concat(NIF.substring(1,8))) == crcChar;
		} else {
			return Common.checksumNIF(NIF.substring(0,8)) == crcChar;
		}
	}
	return false;
};

/**
 * Extend basic form to access raw values.
 */
Ext.override(Ext.form.BasicForm, {

	getRawValues: function() {
		var result = {}, name = null, value = null;
		this.items.each(function(f) {
			if (f.hiddenField != null && f.hiddenName != null) {
				name = f.hiddenName;
				value = f.hiddenField.value;
			} else {
				if (f.name != null) {
					name = f.name;
				} else {
					name = f.hiddenName;
				}
				value = f.getRawValue();
			}
			if (name && value != '') {
				result[name] = value;
			}
		});
		return result;
	}

});

// TODO: http://extjs.com/forum/showthread.php?p=126580#post126580

/**
 * Extend form panel to add each form field a reference to the BasicForm container.
 */
Ext.override(Ext.FormPanel, {

	initFields : function() {
		var f = this.form;
		var formPanel = this;
		var fn = function(c) {
			if (c.doLayout && c != formPanel) {
				Ext.applyIf(c, {
					labelAlign: c.ownerCt.labelAlign,
					labelWidth: c.ownerCt.labelWidth,
					itemCls: c.ownerCt.itemCls
				});
				if (c.items) {
					c.items.each(fn);
				}
			} else if (c.isFormField) {
				f.add(c);
				// Add reference
				c.form = f;
			}
		};
		this.items.each(fn);
	}

});

/**
 * Extend button to allow override of icon background.
 */
Ext.override(Ext.Button, {

	setIcon: function(icon) {
		this.icon = icon;
		this.el.child(this.buttonSelector).setStyle('background-image', 'url(' + this.icon + ')');
	}

});

/**
 * Additional vtypes.
 */
Ext.apply(Ext.form.VTypes, {

	/**
	 * Date range.
	 *
	 * @param val the value.
	 * @param field the field.
	 */
	daterange: function(val, field) {
		var date = field.parseDate(val);

		// We need to force the picker to update values to recaluate the disabled dates display
		var dispUpd = function(picker) {
			var ad = picker.activeDate;
			picker.activeDate = null;
			picker.update(ad);
		};

		if (field.startDateField) {
			var sd = Ext.getCmp(field.startDateField);
			sd.maxValue = date;
			if (sd.menu && sd.menu.picker) {
				sd.menu.picker.maxDate = date;
				dispUpd(sd.menu.picker);
			}
		} else if (field.endDateField) {
			var ed = Ext.getCmp(field.endDateField);
			ed.minValue = date;
			if (ed.menu && ed.menu.picker) {
				ed.menu.picker.minDate = date;
				dispUpd(ed.menu.picker);
			}
		}
		/**
		 * Always return true since we're only using this vtype
		 * to set the min/max allowed values (these are tested
		 * for after the vtype test)
		 */
		return true;
	},

	/**
	 * Repeated value.
	 *
	 * @param val the value.
	 * @param field the linked field.
	 */
	repeated: function(val, field) {
		if (field.form && field.repeatedField) {
			var repeatField = field.form.findField(field.repeatedField);
			if (repeatField != null) {
				return (val == repeatField.getValue());
			}
		}
		return true;
	},

	repeatedText: 'The field does not match the verification field value',

	DNI: function(v) {
		return Common.validateNIF(v);
	},

	dniText : 'Ha introducido un DNI erroneo',
	
	surveyCode : function(v) {
		return /^[a-zA-Z0-9-áéíóúñ\\]{5}$/.test(v);
	},
	
	surveyCodeText : 'Bad Survey Code',
	
	questionCode : function(v) {
			return /^\d{3}$/.test(v);
	},
	
	questionCodeText: 'Bad Question Code',
	
	fullName : function(v) {
		return /^[a-zA-ZáéíóúñÑ-]+\s[a-zA-ZáéíóúñÑ-]+[\s[a-zA-ZáéíóúñÑ-]+]*$/.test(v);
	},
	
	fullNameText : 'Bad Full Name'
});

/**
 * Linkable combo
 *
 * @param config the configuration.
 */
Common.LinkableCombo = function(config) {
	Common.LinkableCombo.superclass.constructor.call(this, config);
};

Ext.extend(Common.LinkableCombo, Ext.form.ComboBox, {

	// private
	linkedFieldType: null,

	// private
	linkParam : null,

	linkedFields : null,

	initComponent: function() {

		this.listeners = {
			blur: function () {
				if (this.getRawValue() == "") {
					this.clearValue();
				}
			}
		};

		this.linkedFields = new Array();
		this.defaultBaseParams = this.store.baseParams;

		Common.LinkableCombo.superclass.initComponent.call(this);
	},

	addLinkedField: function(linkedField) {
		if (linkedField != null) {
			this.linkedFields.push(linkedField);
			if (linkedField.onChange) {
				this.on("select", linkedField.onChange, linkedField);
			}
		}
	},

	onChange: function(element, r, i) {

		if (element.linkParam != null) {
			this.store.baseParams[element.linkParam] = element.getValue();
		}
		this.setValue('');
		this.reset();
		this.lastQuery = 'all';
		this.store.removeAll();
		// this.doQuery(this.getRawValue(), true);
	},

	clearLinkParam: function(linkParam) {
		this.store.baseParams[linkParam] = null;
		this.lastQuery = 'all';
		this.store.removeAll();
		this.setValue('');
	},

	reset: function() {
		Ext.form.ComboBox.superclass.reset.call(this);

		for (var i = 0; i < this.linkedFields.length; i++) {
			this.linkedFields[i].clearLinkParam(this.linkParam);
		}
	}

});

Ext.reg('linkedcombo', Common.LinkableCombo);

/**
 * Icon combo plugin.
 *
 * @param config the configuration.
 */
Common.IconCombo = function(config) {
	Ext.apply(this, config);
};

Ext.extend(Common.IconCombo, Ext.util.Observable, {

	init:function(combo) {
		Ext.apply(combo, {
			tpl:	'<tpl for=".">'
					+ '<div class="x-combo-list-item ux-icon-combo-item '
					+ '{' + combo.iconClsField + '}">'
					+ '{' + combo.displayField + '}'
					+ '</div></tpl>',

			onRender:combo.onRender.createSequence(function(ct, position) {
				// adjust styles
				this.wrap.applyStyles({position:'relative'});
				this.el.addClass('ux-icon-combo-input');

				// add div for icon
				this.icon = Ext.DomHelper.append(this.el.up('div.x-form-field-wrap'), {
					tag: 'div', style:'position:absolute'
				});
			}),

			setIconCls:function() {
				if (this.getValue() != '') {
					var rec = this.store.query(this.valueField, this.getValue()).itemAt(0);
					if (rec && this.icon) {
						this.icon.className = 'ux-icon-combo-icon ' + rec.get(this.iconClsField);
					}
				} else {
					if (this.icon) {
						this.icon.className = 'ux-icon-combo-icon ';
					}
				}
			},

			setValue:combo.setValue.createSequence(function(value) {
				this.setIconCls();
			}),

			setRawValue:combo.setRawValue.createSequence(function(value) {
				this.setIconCls();
			})
		});
	}
});


/**
 * Languages
 */
Common.Languages = [
	['es_ES', MSG['es_ES'], 'spain'],
	['gl_ES', MSG['gl_ES'], 'galicia'],
	['en_US', MSG['en_US'], 'usa']
];

/**
 * Full roles.
 */
Common.Roles = [
	[1, MSG['role.administrator']],
	[2, MSG['role.organization.admin']],
	[3, MSG['role.organization.designer']],
	[4, MSG['role.organization.user']]
];

/**
 * Limited roles.
 */
Common.LimitedRoles = [
	[2, MSG['role.organization.admin']],
	[3, MSG['role.organization.designer']],
	[4, MSG['role.organization.user']]
];

/**
 * Yes No.
 */
Common.YesNo = [
	['true', MSG['yes']],
	['false', MSG['no']]
];

/**
 * Autonomies.
 */
Common.Autonomies = [
	[1,	'Andalucía'],
	[2,	'Aragón'],
	[3,	'Principado de Asturias'],
	[4,	'Islas Baleares'],
	[5,	'País Vasco'],
	[6,	'Canarias'],
	[7,	'Cantabria'],
	[8,	'Castilla-La Mancha'],
	[9,	'Castilla y León'],
	[10, 'Cataluña'],
	[11, 'Extremadura'],
	[12, 'Galicia'],
	[13, 'Comunidad de Madrid'],
	[14, 'Región de Murcia'],
	[15, 'Comunidad Foral de Navarra'],
	[16, 'La Rioja'],
	[17, 'Comunidad Valenciana']
];

/**
 * Provinces.
 */
Common.Provinces = [
	['01', 'Álava'],
	['02', 'Albacete'],
	['03', 'Alicante/Alacant'],
	['04', 'Almería'],
	['05', 'Ávila'],
	['06', 'Badajoz'],
	['07', 'Balears (Illes)'],
	['08', 'Barcelona'],
	['09', 'Burgos'],
	['10', 'Cáceres'],
	['11', 'Cádiz'],
	['12', 'Castellón/Castelló'],
	['13', 'Ciudad Real'],
	['14', 'Córdoba'],
	['15', 'Coruña (A)'],
	['16', 'Cuenca'],
	['17', 'Girona'],
	['18', 'Granada'],
	['19', 'Guadalajara'],
	['20', 'Guipúzcoa'],
	['21', 'Huelva'],
	['22', 'Huesca'],
	['23', 'Jaén'],
	['24', 'León'],
	['25', 'Lleida'],
	['26', 'Rioja (La)'],
	['27', 'Lugo'],
	['28', 'Madrid'],
	['29', 'Málaga'],
	['30', 'Murcia'],
	['31', 'Navarra'],
	['32', 'Ourense'],
	['33', 'Asturias'],
	['34', 'Palencia'],
	['35', 'Palmas (Las)'],
	['36', 'Pontevedra'],
	['37', 'Salamanca'],
	['38', 'Santa Cruz de Tenerife'],
	['39', 'Cantabria'],
	['40', 'Segovia'],
	['41', 'Sevilla'],
	['42', 'Soria'],
	['43', 'Tarragona'],
	['44', 'Teruel'],
	['45', 'Toledo'],
	['46', 'Valencia/València'],
	['47', 'Valladolid'],
	['48', 'Vizcaya'],
	['49', 'Zamora'],
	['50', 'Zaragoza'],
	['51', 'Ceuta'],
	['52', 'Melilla']
];


Common.SurveyLifecycles = [
	[1,	MSG['survey.design']],
	[2,	MSG['survey.production']],
	[3,	MSG['survey.closed']],
	[4,	MSG['survey.archived']]
];

Common.TrainingPreferences = [
	[1,	MSG['training.presential']],
	[2,	MSG['training.remote']],
	[3,	MSG['training.mixed']]
];

Common.PageSize = [
	[10, '10'],
	[20, '20'],
	[30, '30'],
	[50, '50'],
	[100, '100'],
	[200, '200'],
	[500, '500']
];

Common.InternetConnection  = [
	[1, MSG['yes']],
	[0, MSG['no']]
];

Common.ImportedFileStatus  = [
	[1, MSG['file.status.uploaded'] ],
	[2, MSG['file.status.validated'] ],
	[3, MSG['file.status.discarded'] ],
	[4, MSG['file.status.imported'] ]
];

Common.SurveyAnswerStatus  = [
	[0, MSG['survey.answer.invalid'] ],
	[1, MSG['survey.answer.valid'] ],
	[2, MSG['survey.answer.duplicated'] ]
];

Common.SurveyHeaderStatus  = [
	[0, MSG['survey.header.invalid'] ],
	[1, MSG['survey.header.valid'] ],
	[2, MSG['survey.header.duplicated'] ],
	[3, MSG['survey.header.expired'] ]
];


/**
 * Page size plugin for pagin toolbars.
 *
 * @param itemsPerPageText the i18n text.
 */
Common.PageSizePlugin = function(itemsPerPageText) {

	this.itemsPerPageText = itemsPerPageText || "items per page";

	Common.PageSizePlugin.superclass.constructor.call(this, {
		store: new Ext.data.SimpleStore({
			fields: ['id', 'name'],
			data: Common.PageSize
		}),
		mode: 'local',
		displayField: 'name',
		valueField: 'id',
		allowBlank: false,
		forceSelection: true,
		selectOnFocus: true,
		triggerAction: 'all',
		width: 60
	});
};

Ext.extend(Common.PageSizePlugin, Ext.form.ComboBox, {

	init: function(paging) {
		paging.on('render', this.onInitView, this);
	},

	onInitView: function(paging) {
		paging.add('-', this.itemsPerPageText, this);
		this.setValue(paging.pageSize);
		this.on('select', this.onPageSizeChanged, paging);
		this.on('blur', function(){
			if (this.getRawValue() == "") {
				this.clearValue();
			}
		}, this);
	},

	onPageSizeChanged: function(combo) {
		this.pageSize = parseInt(combo.getValue());
		this.doLoad(0);
	}
});

/**
 * Language combo box.
 *
 * @param config the configuration.
 */
Common.LanguageCombo = function(config) {
	Common.LanguageCombo.superclass.constructor.call(this, config);
};

Ext.extend(Common.LanguageCombo, Ext.form.ComboBox, {

	data: null,

	initComponent: function() {

		this.plugins = new Common.IconCombo();

		if (this.data == null) {
			this.data = Common.Languages;
		}

		this.width = 100;

		this.store = new Ext.data.SimpleStore({
			fields: ['id', 'name', 'icon'],
			data: this.data
		});
		if (this.hiddenName == null) {
			this.hiddenName = 'language';
		}
		this.mode = 'local';
		this.fieldLabel = MSG['user.language'];
		this.valueField = 'id';
		this.displayField = 'name';
		this.iconClsField = 'icon';
		this.triggerAction = 'all';
		this.forceSelection = true;
		this.allowBlank = false;
		this.selectOnFocus = true;
		this.selectedClass = 'x-iconcombo-selected';

		this.listeners = {
			blur: function () {
				if (this.getRawValue() == "") {
					this.clearValue();
				}
			}
		};

		Common.LanguageCombo.superclass.initComponent.call(this);
	}
});

Ext.reg('langcombo', Common.LanguageCombo);


/**
 * Simple combo
 */
Common.SimpleCombo = function(config) {
	Common.SimpleCombo.superclass.constructor.call(this, config);
};


Ext.extend(Common.SimpleCombo, Ext.form.ComboBox, {

	data: null,

	initComponent: function() {

		this.store = new Ext.data.SimpleStore({
			fields: ['id', 'name'],
			data: this.data
		});

		if (this.name) {
			this.hiddenName = this.name;
		} else if (this.hiddenName) {
			this.name = this.hiddenName;
		}

		this.mode = 'local';
		this.valueField = 'id';
		this.displayField = 'name';
		this.triggerAction = 'all';
		this.forceSelection = true;
		this.selectOnFocus = true;
		this.lazyRender = true;
		this.typeAhead = true;

		this.listeners = {
			blur: function () {
				if (this.getRawValue() == "") {
					this.clearValue();
				}
			}
		};

		Common.SimpleCombo.superclass.initComponent.call(this);
	}
});

Ext.reg("simplecombo", Common.SimpleCombo);


/**
 * Notifies of a successful operation.
 *
 * @param theTitle title.
 * @param theMessage message
 */
function notifySuccess(theTitle, theMessage) {
	var notification = new Ext.ux.Notification({
		iconCls: 'x-icon-success',
		title: theTitle,
		html: theMessage,
		autoDestroy: true,
		hideDelay: 4000
	}).show(document);
};

/**
 * Notifies of an informational message.
 *
 * @param theTitle title.
 * @param theMessage message
 */
function notifyInformation(theTitle, theMessage) {
	var notification = new Ext.ux.Notification({
		iconCls: 'x-icon-information',
		title: theTitle,
		html: theMessage,
		autoDestroy: true,
		hideDelay: 4000
	}).show(document);
};

/**
 * Notifies of an unsuccessful operation.
 *
 * @param theTitle title.
 * @param theMessage message
 */
function notifyError(theTitle, theMessage) {
	var notification = new Ext.ux.Notification({
		iconCls: 'x-icon-error',
		title: theTitle,
		html: theMessage,
		autoDestroy: true,
		hideDelay: 4000
	}).show(document);
};


/**
 * Password dialog.
 *
 * @param config the configuration.
 */
Common.PasswordDialog = function(config) {
	Common.PasswordDialog.superclass.constructor.call(this, config);
};

Ext.extend(Common.PasswordDialog, Ext.Window, {

	user: null,

	formPanel: null,

	initComponent: function() {
		this.renderTo = Ext.getBody();
		this.modal = true;
		this.iconCls = 'icon-key-edit';
		this.title = MSG['user.password'];
		this.bodyStyle = 'padding:5px';

		this.formPanel = new Ext.FormPanel({
			width: '100%',
			labelWidth: 75,
			frame:true,
			bodyStyle:'padding: 5px',
			defaults: {
				width: 230
			},
			defaultType: 'textfield',
			items: [{
				xtype: 'hidden',
				name: 'id',
				value: this.user.id
			}, {
				xtype: 'textfield',
				name: 'password',
				fieldLabel: MSG['user.password'],
				inputType: 'password',
				maxLength: 12,
				allowBlank: false
			}, {
				xtype: 'textfield',
				name: 'password-repeated',
				labelSeparator: '',
				inputType: 'password',
				maxLength: 12,
				allowBlank: false,
				vtype: 'repeated',
				repeatedField: 'password'
			}],
			buttons: [{
				text: MSG['button.save'],
				iconCls: 'icon-ok',
				handler: this.onSave,
				scope: this
			},{
				text: MSG['button.cancel'],
				iconCls: 'icon-cancel',
				handler: this.onCancel,
				scope: this
			}]
		});

		this.items = this.formPanel;

		Common.PasswordDialog.superclass.initComponent.call(this);
	},

	onSave: function() {
		var theForm = this.formPanel.getForm();

		if (theForm.isValid()) {
			theForm.submit({
				url: CONTEXT_PATH + '/secure/mypassword.json',
				method: 'POST',
				clientValidation: true,
				waitTitle: MSG['wait.title'],
				waitMsg: MSG['wait.message'],
				success: this.onChangeSuccess,
				failure: this.onChangeError,
				scope: this
			});
		} else {
			notifyInformation(MSG['user.update.password'], MSG['user.update.password.not.match']);
		}
	},

	onCancel: function() {
		this.close();
	},

	onChangeSuccess: function(form, action) {
		this.close();
		notifySuccess(MSG['user.update.password'], MSG['user.update.password.success']);
	},

	onChangeError: function(form, action) {
		this.close();
		notifyError(MSG['user.update.password'], MSG['user.update.password.error']);
	}

});


/**
 * CheckPanel.
 *
 * @param config the configuration.
 */
Common.CheckPanel = function(config) {
	Common.CheckPanel.superclass.constructor.call(this, config);
};

Ext.extend(Common.CheckPanel, Ext.Panel, {

	storeFields: null,

	checkName: null,

	columns: null,

	emptyText: null,

	// private

	waitDlg: null,

	resultsStore: null,

	resultsGrid: null,

	initComponent: function()  {
		this.layout = 'border';
		this.closable = true;
		this.autoShow = true;

		if(this.emptyText == null) {
			this.emptyText = MSG['pagination.empty'];
		}

		this.resultsStore = new Ext.data.JsonStore({
			url: CONTEXT_PATH + '/secure/orgadmin/check.json',
			root: 'results',
			totalProperty: 'total',
			remoteSort: false,
			fields: this.storeFields,
			baseParams: { name: this.checkName }
		});

		this.resultsStore.on("beforeload", function() {
			this.waitDlg = Ext.Msg.wait(MSG['wait.title'], MSG['wait.text']);
		}, this);

		this.resultsStore.on("load", function() {
			this.waitDlg.hide();
		}, this);

		this.resultsGrid = new Ext.grid.GridPanel({
			title: this.title,
			region: 'center',
			viewConfig: {
				emptyText: this.emptyText,
				forceFit: true,
				deferEmptyText: true
			},
			cm: new Ext.grid.ColumnModel(this.columns),
			store: this.resultsStore
		});

		this.items = [this.resultsGrid];

		this.resultsStore.load();

		Common.CheckPanel.superclass.initComponent.call(this);

	}

});


Common.ComboRenderer = function(combo) {

	return function(value) {
		var idx = combo.store.find(combo.valueField, value);
		var rec = combo.store.getAt(idx);
		return (rec == null ? '' : rec.get(combo.displayField) );
	};

};


Common.CellRenderer = function (val, cell, record, row, col, store) {
	
	if (record != undefined) {
		if (val == '') {
			cell.css += ' x-form-invalid';
			cell.attr = 'ext:qtip="Please enter a value"; ext:qclass="x-form-invalid-tip"';
		} else {
			cell.css = '';
			cell.attr = 'ext:qtip=""';
		};
	};
	return val;
};
